package de.karlNet.sshTray.controller;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

import de.karlNet.sshTray.datasources.IChangeListener;
import de.karlNet.sshTray.datasources.IChangeListenerProvider;
import de.karlNet.sshTray.datasources.IDataSource;
import de.karlNet.sshTray.model.Connection;
import de.karlNet.sshTray.model.Type;

@Component
public class TypeController implements IChangeListenerProvider {
	@Autowired
	private List<IChangeListener> changeListeners;
	private XStream xStream = new XStream(new DomDriver());
	private File file = new File("typeConnections");

	private IDataSource dataSource;

	@javax.annotation.PostConstruct
	public void init() {
		if (!file.exists()) {
			try {
				file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public TypeController() {
		
	}
	
	public TypeController(IDataSource dataSource) {
		this.dataSource = dataSource;

	}

	public List<Type> readTypes() {
		FileReader reader = null;
		try {
			reader = new FileReader(this.file);
			@SuppressWarnings("unchecked")
			List<Type> connections = (List<Type>) xStream.fromXML(reader);
			reader.close();
			return connections;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			try {
				reader.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
		return new ArrayList<Type>();
	}

	public void createOrUpdateType(Type type) {
		List<Type> types = this.readTypes();
		if (type.getId() == null) {
			type.setId(UUID.randomUUID().getLeastSignificantBits());
			types.add(type);
		} else {
			int index = types.indexOf(type);
			types.remove(index);
			types.add(index, type);

			for (Connection connection : this.dataSource.readConnections()) {
				if (connection.getType().equals(type)) {
					connection.setType(type);
					this.dataSource.createOrUpdateConnection(connection);
				}
			}
		}
		writeData(types);
	}

	private void writeData(List<Type> connections) {

		FileWriter fileReader;
		try {
			fileReader = new FileWriter(this.file);
			xStream.toXML(connections, fileReader);
			fileReader.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		this.notifyChangeListeners();
	}

	public void deleteType(Type type) {
		List<Type> types = this.readTypes();
		if (types.remove(type)) {
			for (Connection connection : this.dataSource.readConnections()) {
				if (connection.getType().equals(type)) {
					// also delete connection
					this.dataSource.deleteConnection(connection);
				}
			}
			writeData(types);
		} else {
			throw new IndexOutOfBoundsException("Element not found");
		}
	}

	

	private void notifyChangeListeners() {
		for (IChangeListener changeListener : this.changeListeners) {
			changeListener.dataHasBeenUpdated();
		}
	}
}
